<?php

namespace siafei\Reporting;

use Throwable;
use Illuminate\Support\Facades\Log;
use function Couchbase\defaultDecoder;


class DingTalkReporting implements ReportInterface
{

    private $webHook;

    private $accessToken;

    private $secret;


    public function __construct($config)
    {
        $this->webHook = $config['web_hook'];
        $this->accessToken = $config['access_token'];
        $this->secret = $config['secret'];
    }

    /**
     * 发送消息
     * @param $message
     * @return array|mixed|void
     */
    public function report($message)
    {
        if (!$message) {
            return;
        }
        if ($message instanceof throwable) {
            $message = $this->initExceptionInfo($message);
        }
        if (!is_string($message)) {
            $message = json_encode($message, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        }

        $this->savelog($message);

        $time = time() * 1000;
        $sign = $this->getSign($time);

        $arr = [
            'headers' => ['Content-Type' => 'application/json'],
            'json' => [
                'msgtype' => 'text',
                'text' => [
                    'content' => $message,
                ]
            ],
        ];

        $url = '?access_token=' . $this->accessToken . '&timestamp=' . $time . '&sign=' . $sign;
        $url = $this->webHook . $url;

        $client = new \GuzzleHttp\Client();
        $res = $client->post($url, $arr);
        $body = $res->getBody()->getContents();
        return empty($body) ? [] : json_decode($body, true);

    }

    /**
     * 日记记录操作
     *
     * @param $msg
     */
    public function savelog($msg = '')
    {
        Log::error('异常错误', ['info' => $msg]);
    }

    /**
     * 服务器信息
     *
     * @param Throwable $e
     *
     * @return string
     */
    public function initExceptionInfo(Throwable $e)
    {
        $projectEnv = $this->getProjectEnv();
        $requestTime = date('Y-m-d H:i:s', $this->getServerEnv('REQUEST_TIME'));
        $requestUrl = $this->getServerEnv('REQUEST_URI');
        $requestParams = [];
        if (in_array($this->getServerEnv('REQUEST_METHOD'), ['GET', 'POST', 'PUT', 'DELETE'])) {
            $requestParams = $_REQUEST;
        }
        $excptMsg = $e->getMessage();
        //$traceDetail = array_slice($e->getTrace(), 0, 2);
        $traceLines = array_slice(explode(PHP_EOL, $e->getTraceAsString()), 0, 2);
        array_push($traceLines, '...');
        // 请求地址描述
        $requestPathInfo = $this->getServerEnv('PATH_INFO');
        // 异常消息描述
        $exceptMsgDesc = mb_substr($excptMsg, 0, 50);
        $exceptMsgDesc = str_replace(["\n", "\r", "'", '"', "\t", "\0", "\x0B"], '', $exceptMsgDesc);
        $exceptMsgDesc = trim($exceptMsgDesc);

        //$subject = "请求{$requestPathInfo}异常：{$exceptMsgDesc}";
        $info = [
            '系统名称' => getenv('APP_NAME'),
            '异常类' => [
                '文件' => $e->getFile(),
                '行数' => $e->getLine(),
                '异常类' => get_class($e),
                '异常code' => $e->getCode(),
                '异常消息' => $excptMsg,
            ],
            //'异常StackTrace概述' => $traceLines,
            '请求' => [
                '请求时间' => $requestTime,
                '请求方法' => $this->getServerEnv('REQUEST_METHOD'),
                '请求地址' => $requestUrl,
                '请求参数' => $requestParams,
            ],
            '环境' => [
                '项目环境' => $projectEnv,
                '站点名称' => $this->getServerEnv('SERVER_NAME'),
                '服务器IP' => $this->getServerEnv('SERVER_ADDR'),
                '变量APP_ENV' => $this->getServerEnv('APP_ENV'),
                '变量SITE_LOG_DIR' => $this->getServerEnv('LOG_DIR'),
            ],
        ];

        return json_encode($info, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    }

    /**
     * 安全获取环境变量
     *
     * @param $attr
     *
     * @return mixed|null
     */
    public function getServerEnv($attr)
    {
        return $_SERVER[$attr] ?? null;
    }

    /**
     * 获取客户端ip
     *
     * @return mixed|null
     */
    final public function getClientIP()
    {
        $ip = null;
        !$ip && !empty($_SERVER["REMOTE_ADDR"]) && $ip = $_SERVER["REMOTE_ADDR"];
        !$ip && !empty($_SERVER['HTTP_CLIENT_IP']) && $ip = $_SERVER['HTTP_CLIENT_IP'];
        !$ip && !empty($_SERVER['HTTP_X_FORWARD_FOR']) && $ip = $_SERVER['HTTP_X_FORWARD_FOR'];
        return $ip;
    }

    /**
     * 是否是生产环境
     *
     * @return string
     */
    public function getProjectEnv()
    {
        return getenv('APP_ENV') ?? '未知环境';
    }

    /**
     * 获取签名
     * @param $time
     * @return string
     */
    protected function getSign($time)
    {
        $sign = hash_hmac('sha256', $time . "\n" . $this->secret, $this->secret, true);
        $sign = base64_encode($sign);
        $sign = urlencode($sign);
        return $sign;
    }
}